/*
    backend for TimeTagger, an OpalKelly based single photon counting library
    Copyright (C) 2011  Markus Wick <wickmarkus@web.de>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <assert.h>
#include <sstream>

#include "TimeTagger.h"
#include "CountBetweenMarkers.h"

#include "Logger.h"
DECLARE_LOG_SUPPORT(MODULES)

CountBetweenMarkers::CountBetweenMarkers(int _counter, int _marker, int _bins) {
	debug("CountBetweenMarkers created.");
	counter = _counter;
	marker = _marker;
	bins = _bins;

	data = new int[bins];

	clear();

	registerChannel(counter);
	registerChannel(marker);
	start();
}

CountBetweenMarkers::~CountBetweenMarkers() {
	stop();
	delete [] data;
}

const char *CountBetweenMarkers::getClassName() {
	return "CountBetweenMarkers";
}

const char *CountBetweenMarkers::getScpiCommand() {
	return ":CONFigure:COUNTBeetweenmarkers";
}

std::string CountBetweenMarkers::getScpiParameters() {
	std::stringstream ss;
	ss << "chan" << counter << ",chan" << marker << '(' << bins << ')';
	return ss.str();
}

void CountBetweenMarkers::getMeta(long long **ARGOUTVIEWM_ARRAY2, int *DIM1) {
	const int sz=4;
	long long *arr = new long long[sz];

	synchronized(*this) {
		long long *ptr=arr;
		*ptr++=counter;
		*ptr++=marker;
		*ptr++=bins;
		*ptr++=state;
	}

	*ARGOUTVIEWM_ARRAY2 = arr;
	*DIM1 = sz;
}


void CountBetweenMarkers::clear() {
	lock();

	state = -1;
	for(int i=0; i<bins; i++)
		data[i] = 0;
	
	unlock();
}

bool CountBetweenMarkers::ready() {
	lock();
	bool wert = state >= bins;
	unlock();

	return wert;
}

void CountBetweenMarkers::getData(int **ARGOUTVIEWM_ARRAY1, int *DIM1, bool blocking) {
	assert(data);

	int *arr = new int[bins];

	assert(arr);

	while(blocking && !ready())
		current_sleep(10);

	lock();

	for ( int i=0; i<bins; i++) {
		arr[i] = data[i];
	}

	*ARGOUTVIEWM_ARRAY1 = arr;
	*DIM1 = bins;

	unlock();
}

void CountBetweenMarkers::next(Tag* list, int count, long long time) {
	for(int i=0; i<count; i++) {
		if(list[i].chan == marker && state < bins)
			state++;
		if(list[i].chan == counter && state >= 0 && state < bins) {
			data[state]++;
		}
	}
}
